import io
import os
import sys
def calc_lps(pat):
lps = [-1] * len(pat)
cand = -1
for i in range(1, len(pat)):
while cand >= 0 and pat[i] != pat[cand + 1]:
cand = lps[cand]
if pat[i] == pat[cand + 1]:
cand += 1
lps[i] = cand
return lps
s = input()
n = len(s)
lps = calc_lps(s)
cnt = [1] * (n + 1)
for i in range(n - 1, 0, -1):
if lps[i] >= 0:
cnt[lps[i] + 1] += cnt[i + 1]
ans = []
cur = n - 1
while cur != -1:
ans.append((cur + 1, cnt[cur + 1]))
cur = lps[cur]
print(len(ans))
for l, c in ans[::-1]:
print(l, c)
#include <bits/stdc++.h>
using namespace std;
const int N_MAX = 1e5;
/// Observatii si comentarii :
/// In primul rand trebuie sa aflam prefixele care respecta conditia din enunt
/// Cel mai lung dintre ele este chiar raspunsul dat de KMP --> LPS[n - 1]
/// Fie Pk lungimea prefixului curent. Atunci urmatorul cel mai lung prefix va fi cel de lungime LPS[Pk - 1]
/// Nota : Sirul de lungime n se adauga la inceput cu frecventa 1
/// In al doilea rand trebuie sa aflam frecventele acestor prefixe
/// Ne propunem sa aflam pentru o pozitie i sa aflam ce prefixe se termina pe acea pozitie
/// In aceeasi maniera, cel mai lung dintre ele este LPS[i]
/// Fie Pk prefixului curent. Atunci urmatorul cel mai lung prefix va fi cel de lungime LPS[Pk - 1]
/// Astfel pentru fiecare pozitie i = 0..n - 1 se formeaza un sir de prefixe care apar
/// Aceste siruri sunt descrescatoare si urmeaza regula prefix --> LPS[prefix - 1]
/// Momentan noi cunoastem doar frecventa "sefilor" de sir (primului numar din sir)
/// Pentru a frecventa lui LPS[prefix - 1] trebuie mai intai sa aflam frecventa lui prefix
/// Asadar ar fi minunat daca am gasi o sortare topologica a acestor prefixe
/// => graful format de aceste prefix trebuie sa fie unul directionat si aciclic
/// cunoastem ca este directionat si este chiar si aciclic deoarece sirurile sunt descrescatoare
/// Altfel spus, nu ne putem intoarce de la ceva mic la ceva mare
/// Asadar formam graful, il sortam topologic iar frecv[LPS[prefix - 1]] += frecv[prefix]
/// deoarece unde apare prefix sigur apare si LPS[prefix - 1]
int LPS[1 + N_MAX];
int frecv[1 + N_MAX];
vector<int> DAG[1 + N_MAX];
void KMP (string input) {
int n = input.size (); LPS[0] = 0;
int k = 0; /// curr lps
for (int i = 1; i < n; i ++) {
while (k > 0 && input[i] != input[k])
k = LPS[k - 1];
if (input[i] == input[k])
k ++;
LPS[i] = k;
frecv[k] ++;
if (frecv[k] == 1) /// adaosul prefix -- LPS[prefix - 1] trebuie sa se intample exact o data
DAG[k].push_back (LPS[k - 1]);
}
}
vector<int> topoSort;
bool visited[1 + N_MAX];
void dfs (int root) {
visited[root] = true;
for (int node : DAG[root])
if (!visited[node])
dfs (node);
topoSort.push_back (root);
}
struct defAnswer {
int preff, counter;
};
int main()
{
string input; cin >> input;
KMP (input);
int n = input.size ();
for (int preff = 0; preff < n; preff ++)
if (!visited[preff])
dfs (preff);
reverse (topoSort.begin (), topoSort.end ());
for (int node : topoSort) {
for (int u : DAG[node])
frecv[u] += frecv[node];
}
vector<defAnswer> answer;
answer.push_back ({n, 1});
int k = LPS[n - 1];
while (k > 0) {
answer.push_back ({k, 1 + frecv[k]}); /// adunam 1 pentru a considera si prefixul in sine care NU este considerat de KMP
k = LPS[k - 1];
}
reverse (answer.begin (), answer.end ());
cout << answer.size () << "\n";
for (defAnswer obj : answer) {
cout << obj.preff << " " << obj.counter;
cout << "\n";
}
return 0;
}
519A - A and B and Chess | 725B - Food on the Plane |
154B - Colliders | 127B - Canvas Frames |
107B - Basketball Team | 245A - System Administrator |
698A - Vacations | 1216B - Shooting |
368B - Sereja and Suffixes | 1665C - Tree Infection |
1665D - GCD Guess | 29A - Spit Problem |
1097B - Petr and a Combination Lock | 92A - Chips |
1665B - Array Cloning Technique | 1665A - GCD vs LCM |
118D - Caesar's Legions | 1598A - Computer Game |
1605A - AM Deviation | 1461A - String Generation |
1585B - Array Eversion | 1661C - Water the Trees |
1459A - Red-Blue Shuffle | 1661B - Getting Zero |
1661A - Array Balancing | 1649B - Game of Ball Passing |
572A - Arrays | 1455A - Strange Functions |
1566B - MIN-MEX Cut | 678C - Joty and Chocolate |